export class Shader {
  private gl: WebGLRenderingContext;
  private program: WebGLProgram | null = null;
  private uniformLocations: Map<string, WebGLUniformLocation> = new Map();

  constructor(gl: WebGLRenderingContext) {
    this.gl = gl;
  }

  async load(vertexShaderPath: string, fragmentShaderPath: string): Promise<boolean> {
    try {
      const [vertexShaderSource, fragmentShaderSource] = await Promise.all([
        fetch(vertexShaderPath).then(res => res.text()),
        fetch(fragmentShaderPath).then(res => res.text())
      ]);

      return this.compile(vertexShaderSource, fragmentShaderSource);
    } catch (error) {
      console.error('加载着色器失败:', error);
      return false;
    }
  }

  compile(vertexSource: string, fragmentSource: string): boolean {
    const gl = this.gl;
    
    // 创建着色器
    const vertexShader = this.createShader(gl.VERTEX_SHADER, vertexSource);
    const fragmentShader = this.createShader(gl.FRAGMENT_SHADER, fragmentSource);
    
    if (!vertexShader || !fragmentShader) {
      return false;
    }

    // 创建程序
    const program = gl.createProgram();
    if (!program) {
      console.error('创建着色器程序失败');
      return false;
    }

    // 附加着色器到程序
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    
    // 链接程序
    gl.linkProgram(program);
    
    // 检查链接状态
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      console.error('链接程序失败:', gl.getProgramInfoLog(program));
      gl.deleteProgram(program);
      return false;
    }

    // 保存程序
    this.program = program;
    
    // 清除着色器资源
    gl.deleteShader(vertexShader);
    gl.deleteShader(fragmentShader);
    
    return true;
  }

  private createShader(type: number, source: string): WebGLShader | null {
    const gl = this.gl;
    const shader = gl.createShader(type);
    
    if (!shader) {
      console.error('创建着色器失败');
      return null;
    }
    
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      console.error(`编译${type === gl.VERTEX_SHADER ? '顶点' : '片元'}着色器失败:`, 
                    gl.getShaderInfoLog(shader));
      gl.deleteShader(shader);
      return null;
    }
    
    return shader;
  }

  use(): void {
    if (this.program) {
      this.gl.useProgram(this.program);
    }
  }

  getUniformLocation(name: string): WebGLUniformLocation | null {
    if (!this.program) return null;
    
    // 检查缓存中是否已存在
    if (this.uniformLocations.has(name)) {
      return this.uniformLocations.get(name) || null;
    }
    
    // 获取位置并缓存
    const location = this.gl.getUniformLocation(this.program, name);
    if (location) {
      this.uniformLocations.set(name, location);
    }
    
    return location;
  }

  // 设置各种类型的Uniform
  setUniform1f(name: string, value: number): void {
    const location = this.getUniformLocation(name);
    if (location) {
      this.gl.uniform1f(location, value);
    }
  }

  setUniform2f(name: string, x: number, y: number): void {
    const location = this.getUniformLocation(name);
    if (location) {
      this.gl.uniform2f(location, x, y);
    }
  }

  setUniform3f(name: string, x: number, y: number, z: number): void {
    const location = this.getUniformLocation(name);
    if (location) {
      this.gl.uniform3f(location, x, y, z);
    }
  }

  setUniform1i(name: string, value: number): void {
    const location = this.getUniformLocation(name);
    if (location) {
      this.gl.uniform1i(location, value);
    }
  }
} 